// BankEvent.cpp

#include "LinkList.cpp"
#include "LinkQueue.cpp"

typedef struct
{
    int OccurTime;      // 事件发生时刻
    int nType;          // 事件类型，0表示到达事件，1至4表示四个窗口的离开事件。
}Event, ElemType;       // 事件类型，有序链表LinkList的数据元素类型。

typedef LinkList EventList;

typedef struct
{
    int ArrivalTime;        // 到达时刻
    int Duration;           // 办理事务所需时间
}QElemType;                 // 队列的数据元素类型

EventList ev;                   // 事件表
Event en;                       // 事件
LinkQueue q[5];                 // 4个客户队列
QElemType customer;             // 客户记录
int totalTime, customerNum;     // 累计客户逗留时间，客户数。

int cmp(Event a, Event b)
{
    // 依事件a的发生时刻<或=或>事件b的发生时刻分别返回-1或0或1
    if(a.OccurTime < b.OccurTime)
    {
        return -1;
    }
    else if(a.OccurTime == b.OccurTime)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

void OpenForDay()
{
    // 初始化操作
    totalTime = 0;                  // 初始化累计时间和客户数为0
    customerNum = 0;
    InitList(ev);                   // 初始化事件链表为空表
    en.OccurTime = 0;               // 设定第一个客户到达事件
    en.nType = 0;
    OrderInsert(ev, en, cmp);       // 插入事件表
    for(int i = 1; i <= 4; ++i)
    {
        InitQueue(q[i]);            // 置空队列
    }
}

void CustomerArrived()
{
    // 处理客户到达事件，en.nType = 0;
    ++customerNum;
    random(durtime, intertime);
    t = en.OccurTime + intertime;

    if(t < closeTime)
    {
        OrderInsert(ev, (t,0), cmp);
    }
    
    int i = minimum(q);

    EnQueue(q[i], (en.OccurTime, durtime));

    if(QueueLength(q[i]) == 1)
    {
        OrderInsert(ev, (en.OccurTime + durtime, i), cmp);
    }
}

void CustomerDeparture()
{
    // 处理客户离开事件，en.nType > 0;
    int i = en.nType;
    DelQueue(q[i], customer);
    totalTime += en.OccurTime - customer.ArrivalTime;

    if(!QueueEmpty(q[i]))
    {
        GetHead(q[i], customer);
        OrderInsert(ev, (en.OccurTime + customer.Duration, i), (*cmp)());
    }
}

void Bank_Simulation(int closeTime)
{
    OpenForDay();

    while(!ListEmpty(ev))
    {
        DelFirst(GetHead(ev), p);
        en = GetCurElem(p);
        if(en.nType == 0)
        {
            CustomerArrived();
        }
        else
        {
            CustomerDeparture();
        }
    }

    printf("The average time is %f\n", (float)totalTime / customerNum);
}
